{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fed6d06a-c5a6-49cd-949c-7d4c9ed9b8a1",
   "metadata": {},
   "source": [
    "# Dynamic Text Positioning with Repel Geometries\n",
    "\n",
    "- `geomTextRepel()`\n",
    "- `geomLabelRepel()`\n",
    "\n",
    "These functions use a force-based layout algorithm to automatically reposition text labels and resolve overlaps.\n",
    "\n",
    "Labels repel each other and their associated data points while staying within the plot boundaries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bd28eb0e-f782-4b58-a250-c2dde64c16e4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "            <div id=\"kotlin_out_0\"></div>\n",
       "            <script type=\"text/javascript\">\n",
       "                            if(!window.kotlinQueues) {\n",
       "                window.kotlinQueues = {};\n",
       "            }\n",
       "            if(!window.kotlinQueues[\"DataFrame\"]) {\n",
       "                var resQueue = [];\n",
       "                window.kotlinQueues[\"DataFrame\"] = resQueue;\n",
       "                window[\"call_DataFrame\"] = function(f) {\n",
       "                    resQueue.push(f);\n",
       "                }\n",
       "            }\n",
       "            (function (){\n",
       "                var modifiers = [(function(script) {\n",
       "    script.src = \"https://cdn.jsdelivr.net/gh/Kotlin/dataframe@3db46ccccaa1291c0627307d64133317f545e6ae/core/src/main/resources/init.js\"\n",
       "    script.type = \"text/javascript\";\n",
       "})];\n",
       "                var e = document.getElementById(\"kotlin_out_0\");\n",
       "                modifiers.forEach(function (gen) {\n",
       "                    var script = document.createElement(\"script\");\n",
       "                    gen(script)\n",
       "                    script.addEventListener(\"load\", function() {\n",
       "                        window[\"call_DataFrame\"] = function(f) {f();};\n",
       "                        window.kotlinQueues[\"DataFrame\"].forEach(function(f) {f();});\n",
       "                        window.kotlinQueues[\"DataFrame\"] = [];\n",
       "                    }, false);\n",
       "                    script.addEventListener(\"error\", function() {\n",
       "                        window[\"call_DataFrame\"] = function(f) {};\n",
       "                        window.kotlinQueues[\"DataFrame\"] = [];\n",
       "                        var div = document.createElement(\"div\");\n",
       "                        div.style.color = 'darkred';\n",
       "                        div.textContent = 'Error loading resource DataFrame';\n",
       "                        document.getElementById(\"kotlin_out_0\").appendChild(div);\n",
       "                    }, false);\n",
       "                    \n",
       "                    e.appendChild(script);\n",
       "                });\n",
       "            })();\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "                <style>\n",
       "                :root {\n",
       "    --background: #fff;\n",
       "    --background-odd: #f5f5f5;\n",
       "    --background-hover: #d9edfd;\n",
       "    --header-text-color: #474747;\n",
       "    --text-color: #848484;\n",
       "    --text-color-dark: #000;\n",
       "    --text-color-medium: #737373;\n",
       "    --text-color-pale: #b3b3b3;\n",
       "    --inner-border-color: #aaa;\n",
       "    --bold-border-color: #000;\n",
       "    --link-color: #296eaa;\n",
       "    --link-color-pale: #296eaa;\n",
       "    --link-hover: #1a466c;\n",
       "}\n",
       "\n",
       ":root[theme=\"dark\"], :root [data-jp-theme-light=\"false\"], .dataframe_dark{\n",
       "    --background: #303030;\n",
       "    --background-odd: #3c3c3c;\n",
       "    --background-hover: #464646;\n",
       "    --header-text-color: #dddddd;\n",
       "    --text-color: #b3b3b3;\n",
       "    --text-color-dark: #dddddd;\n",
       "    --text-color-medium: #b2b2b2;\n",
       "    --text-color-pale: #737373;\n",
       "    --inner-border-color: #707070;\n",
       "    --bold-border-color: #777777;\n",
       "    --link-color: #008dc0;\n",
       "    --link-color-pale: #97e1fb;\n",
       "    --link-hover: #00688e;\n",
       "}\n",
       "\n",
       "p.dataframe_description {\n",
       "    color: var(--text-color-dark);\n",
       "}\n",
       "\n",
       "table.dataframe {\n",
       "    font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n",
       "    font-size: 12px;\n",
       "    background-color: var(--background);\n",
       "    color: var(--text-color-dark);\n",
       "    border: none;\n",
       "    border-collapse: collapse;\n",
       "}\n",
       "\n",
       "table.dataframe th, td {\n",
       "    padding: 6px;\n",
       "    border: 1px solid transparent;\n",
       "    text-align: left;\n",
       "}\n",
       "\n",
       "table.dataframe th {\n",
       "    background-color: var(--background);\n",
       "    color: var(--header-text-color);\n",
       "}\n",
       "\n",
       "table.dataframe td {\n",
       "    vertical-align: top;\n",
       "    white-space: nowrap;\n",
       "}\n",
       "\n",
       "table.dataframe th.bottomBorder {\n",
       "    border-bottom-color: var(--bold-border-color);\n",
       "}\n",
       "\n",
       "table.dataframe tbody > tr:nth-child(odd) {\n",
       "    background: var(--background-odd);\n",
       "}\n",
       "\n",
       "table.dataframe tbody > tr:nth-child(even) {\n",
       "    background: var(--background);\n",
       "}\n",
       "\n",
       "table.dataframe tbody > tr:hover {\n",
       "    background: var(--background-hover);\n",
       "}\n",
       "\n",
       "table.dataframe a {\n",
       "    cursor: pointer;\n",
       "    color: var(--link-color);\n",
       "    text-decoration: none;\n",
       "}\n",
       "\n",
       "table.dataframe tr:hover > td a {\n",
       "    color: var(--link-color-pale);\n",
       "}\n",
       "\n",
       "table.dataframe a:hover {\n",
       "    color: var(--link-hover);\n",
       "    text-decoration: underline;\n",
       "}\n",
       "\n",
       "table.dataframe img {\n",
       "    max-width: fit-content;\n",
       "}\n",
       "\n",
       "table.dataframe th.complex {\n",
       "    background-color: var(--background);\n",
       "    border: 1px solid var(--background);\n",
       "}\n",
       "\n",
       "table.dataframe .leftBorder {\n",
       "    border-left-color: var(--inner-border-color);\n",
       "}\n",
       "\n",
       "table.dataframe .rightBorder {\n",
       "    border-right-color: var(--inner-border-color);\n",
       "}\n",
       "\n",
       "table.dataframe .rightAlign {\n",
       "    text-align: right;\n",
       "}\n",
       "\n",
       "table.dataframe .expanderSvg {\n",
       "    width: 8px;\n",
       "    height: 8px;\n",
       "    margin-right: 3px;\n",
       "}\n",
       "\n",
       "table.dataframe .expander {\n",
       "    display: flex;\n",
       "    align-items: center;\n",
       "}\n",
       "\n",
       "/* formatting */\n",
       "\n",
       "table.dataframe .null {\n",
       "    color: var(--text-color-pale);\n",
       "}\n",
       "\n",
       "table.dataframe .structural {\n",
       "    color: var(--text-color-medium);\n",
       "    font-weight: bold;\n",
       "}\n",
       "\n",
       "table.dataframe .dataFrameCaption {\n",
       "    font-weight: bold;\n",
       "}\n",
       "\n",
       "table.dataframe .numbers {\n",
       "    color: var(--text-color-dark);\n",
       "}\n",
       "\n",
       "table.dataframe td:hover .formatted .structural, .null {\n",
       "    color: var(--text-color-dark);\n",
       "}\n",
       "\n",
       "table.dataframe tr:hover .formatted .structural, .null {\n",
       "    color: var(--text-color-dark);\n",
       "}\n",
       "\n",
       "\n",
       "                </style>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "   <div id=\"6aT3Xo\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"library\">\n",
       "       if(!window.letsPlotCallQueue) {\n",
       "           window.letsPlotCallQueue = [];\n",
       "       }; \n",
       "       window.letsPlotCall = function(f) {\n",
       "           window.letsPlotCallQueue.push(f);\n",
       "       };\n",
       "       (function() {\n",
       "           var script = document.createElement(\"script\");\n",
       "           script.type = \"text/javascript\";\n",
       "           script.src = \"https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v4.7.0/js-package/distr/lets-plot.min.js\";\n",
       "           script.onload = function() {\n",
       "               window.letsPlotCall = function(f) {f();};\n",
       "               window.letsPlotCallQueue.forEach(function(f) {f();});\n",
       "               window.letsPlotCallQueue = [];\n",
       "               \n",
       "               \n",
       "           };\n",
       "           script.onerror = function(event) {\n",
       "               window.letsPlotCall = function(f) {};\n",
       "               window.letsPlotCallQueue = [];\n",
       "               var div = document.createElement(\"div\");\n",
       "               div.style.color = 'darkred';\n",
       "               div.textContent = 'Error loading Lets-Plot JS';\n",
       "               document.getElementById(\"6aT3Xo\").appendChild(div);\n",
       "           };\n",
       "           var e = document.getElementById(\"6aT3Xo\");\n",
       "           e.appendChild(script);\n",
       "       })();\n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "            <div id=\"kotlin_out_1\"></div>\n",
       "            <script type=\"text/javascript\">\n",
       "                            if(!window.kotlinQueues) {\n",
       "                window.kotlinQueues = {};\n",
       "            }\n",
       "            if(!window.kotlinQueues[\"letsPlotJs\"]) {\n",
       "                var resQueue = [];\n",
       "                window.kotlinQueues[\"letsPlotJs\"] = resQueue;\n",
       "                window[\"call_letsPlotJs\"] = function(f) {\n",
       "                    resQueue.push(f);\n",
       "                }\n",
       "            }\n",
       "            (function (){\n",
       "                var modifiers = [(function(script) {\n",
       "    script.src = \"https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v4.7.0/js-package/distr/lets-plot.min.js\"\n",
       "    script.type = \"text/javascript\";\n",
       "})];\n",
       "                var e = document.getElementById(\"kotlin_out_1\");\n",
       "                modifiers.forEach(function (gen) {\n",
       "                    var script = document.createElement(\"script\");\n",
       "                    gen(script)\n",
       "                    script.addEventListener(\"load\", function() {\n",
       "                        window[\"call_letsPlotJs\"] = function(f) {f();};\n",
       "                        window.kotlinQueues[\"letsPlotJs\"].forEach(function(f) {f();});\n",
       "                        window.kotlinQueues[\"letsPlotJs\"] = [];\n",
       "                    }, false);\n",
       "                    script.addEventListener(\"error\", function() {\n",
       "                        window[\"call_letsPlotJs\"] = function(f) {};\n",
       "                        window.kotlinQueues[\"letsPlotJs\"] = [];\n",
       "                        var div = document.createElement(\"div\");\n",
       "                        div.style.color = 'darkred';\n",
       "                        div.textContent = 'Error loading resource letsPlotJs';\n",
       "                        document.getElementById(\"kotlin_out_1\").appendChild(div);\n",
       "                    }, false);\n",
       "                    \n",
       "                    e.appendChild(script);\n",
       "                });\n",
       "            })();\n",
       "            </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%useLatestDescriptors\n",
    "%use dataframe\n",
    "%use lets-plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "81b92ef6-3141-482d-9adf-3313be01ed12",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Lets-Plot Kotlin API v.4.11.0. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.7.0."
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "LetsPlot.getInfo()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ea3ced8d-e043-4373-8f4e-077fba64da34",
   "metadata": {},
   "outputs": [],
   "source": [
    "import kotlin.random.Random\n",
    "import org.jetbrains.letsPlot.interact.ggtb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3ca6c904-55aa-454e-ab16-b121d9100acb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "32 x 12\n",
      "               model  mpg cyl  disp  hp drat    wt  qsec vs am gear carb\n",
      " 0         Mazda RX4 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4\n",
      " 1     Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4\n",
      " 2        Datsun 710 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1\n",
      " 3    Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1\n",
      " 4 Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2\n",
      "\n"
     ]
    }
   ],
   "source": [
    "val df = DataFrame.readCsv(\n",
    "    fileOrUrl = \"https://gist.githubusercontent.com/seankross/a412dfbd88b3db70b74b/raw/5f23f993cd87c283ce766e7ac6b329ee7cc2e1d1/mtcars.csv\",\n",
    "    delimiter = ',',\n",
    "    header = listOf(),\n",
    "    colTypes = mapOf(),\n",
    "    skipLines = 0,\n",
    "    readLines = null,\n",
    "    allowMissingColumns = true,\n",
    "    parserOptions = null\n",
    ")\n",
    "println(df.size())\n",
    "println(df.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a9a5c1ee-a055-47f2-8de7-bdb54f608171",
   "metadata": {},
   "outputs": [],
   "source": [
    "val df1 = df.filter { (2.0 < it[\"wt\"] as Double) && ((it[\"wt\"] as Double) < 3.65) }\n",
    "val df2 = df\n",
    "    .filter { (2.0 < it[\"wt\"] as Double) && ((it[\"wt\"] as Double) < 3) }\n",
    "    .add(\"shape\") { if (it[\"am\"] == 0.0) 16 else 21 }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "35dfc501-3dff-48de-b1ae-dac2f3f86dad",
   "metadata": {},
   "outputs": [],
   "source": [
    "val plot1 = ggplot(df1.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" } + geomPoint(color = \"red\")\n",
    "val plot2 = ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" } + geomPoint(color = \"red\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3c89c08-29a5-4a30-bd6e-a5d157665d9b",
   "metadata": {},
   "source": [
    "### Comparison of geomText() and geomTextRepel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d49a03c5-8719-46ab-a8bd-5f918f868042",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"FnAmwj\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"FnAmwj\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"geomText()\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"1\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"geomTextRepel()\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"2\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomText() + ggtitle(\"geomText()\"),\n",
    "        plot2 + geomTextRepel() + ggtitle(\"geomTextRepel()\")\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1de52948-f9d2-49be-8c22-b264c52038fd",
   "metadata": {},
   "source": [
    "### geomLabelRepel()\n",
    "All of the parameters discussed below apply equally to both `geomTextRepel()` and `geomLabelRepel()`. For simplicity, we will use `geomTextRepel()` in the examples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "12b29f79-b837-445b-ac17-7828818ad354",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"U8UUc0\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"U8UUc0\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"geomText()\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"label\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"3\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"geomTextRepel()\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"label_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"4\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomLabel() + ggtitle(\"geomText()\"),\n",
    "        plot2 + geomLabelRepel() + ggtitle(\"geomTextRepel()\")\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5f55b41-8d5f-497f-b88d-56bbf55b7523",
   "metadata": {},
   "source": [
    "### `seed` parameter\n",
    "\n",
    "Controls the randomization to produce the same label layout each time the plot is generated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6e31322c-0405-41fc-a739-bb6cccdce904",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"D1OcGg\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"D1OcGg\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":2,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Without seed\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"5\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Without seed\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"6\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"With seed\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":4.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"7\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"With seed\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":4.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"8\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomTextRepel() + ggtitle(\"Without seed\"),\n",
    "        plot2 + geomTextRepel() + ggtitle(\"Without seed\"),\n",
    "        plot2 + geomTextRepel(seed = 4) + ggtitle(\"With seed\"),\n",
    "        plot2 + geomTextRepel(seed = 4) + ggtitle(\"With seed\"),\n",
    "    ), ncol = 2\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5017d288-3742-45c3-93ee-babc013fd01f",
   "metadata": {},
   "source": [
    "In some cases, it may be necessary to find a seed value that produces a more optimal label arrangement. A simple approach is to re-render the plot multiple times until you're satisfied with the result, then use the corresponding seed to reproduce it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ab48d9d3-dc79-4962-81a9-447ef179e3da",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"Xyld0U\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"Xyld0U\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Seed = 1972947724\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":1.972947724E9,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"9\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "seed = 1972947724"
     ]
    }
   ],
   "source": [
    "val randomSeed = Random.nextInt()\n",
    "print(\"seed = $randomSeed\")\n",
    "(plot2 + geomTextRepel(seed = randomSeed) + ggtitle(\"Seed = $randomSeed\")).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f91e730-949e-4659-b720-42fde24084a0",
   "metadata": {},
   "source": [
    "### `maxIter` parameter\n",
    "Controls the maximum number of iterations used by the layout algorithm, helping to reduce notebook rendering time. More iterations generally lead to better label placement, but at the cost of increased computation time. For plots with a small number of labels, 200–300 iterations are often sufficient.\n",
    "The default value is 2000."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "bcbce3ae-4a20-40aa-bd88-8b01e1564d1e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"yyjmYj\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"yyjmYj\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":3,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_iter=2\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"max_iter\":2.0,\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"10\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_iter=20\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"max_iter\":20.0,\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"11\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_iter=200\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"max_iter\":200.0,\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"12\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val seed = 530\n",
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomTextRepel(seed = seed, maxIter = 2) + ggtitle(\"max_iter=2\"),\n",
    "        plot2 + geomTextRepel(seed = seed, maxIter = 20) + ggtitle(\"max_iter=20\"),\n",
    "        plot2 + geomTextRepel(seed = seed, maxIter = 200) + ggtitle(\"max_iter=200\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0694f1fd-2144-4179-af25-ee9180c6f349",
   "metadata": {},
   "source": [
    "### `maxTime` parameter\n",
    "Another way to limit plot rendering time is by using the `maxTime` parameter. This primarily serves as a safeguard against excessive computation when a large number of text labels are involved. Time is specified in seconds. The default value is `5` seconds, but you can disable the time limit by setting it to `-1` if needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "6a7e7d37-3426-44c7-b297-d391b1fa1142",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"qs3JrQ\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"qs3JrQ\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":3,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_time=0.001\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":0.001,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"13\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_time=0.01\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":0.01,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"14\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"max_time=-1\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"15\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomTextRepel(seed = seed, maxTime = 0.001) + ggtitle(\"max_time=0.001\"),\n",
    "        plot2 + geomTextRepel(seed = seed, maxTime = 0.01) + ggtitle(\"max_time=0.01\"),\n",
    "        plot2 + geomTextRepel(seed = seed, maxTime = -1.0) + ggtitle(\"max_time=-1\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb6279e2-36ed-4991-9918-066a98e092c1",
   "metadata": {},
   "source": [
    "### `direction` parameter\n",
    "Restricts the movement of a text label relative to its anchor point to a specific direction. The default value is `both`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a64f29ce-417c-4d32-88c1-fee074711f56",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"n90lFD\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"n90lFD\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":3,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"direction = 'x'\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"direction\":\"x\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"16\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"direction = 'y'\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"direction\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"17\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"direction = 'both'\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"direction\":\"both\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"18\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomTextRepel(seed = seed, direction = \"x\") + ggtitle(\"direction = 'x'\"),\n",
    "        plot2 + geomTextRepel(seed = seed, direction = \"y\") + ggtitle(\"direction = 'y'\"),\n",
    "        plot2 + geomTextRepel(seed = seed, direction = \"both\") + ggtitle(\"direction = 'both'\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f770d41-6840-4926-84a5-c1e87418b573",
   "metadata": {},
   "source": [
    "As we can see, this option is of limited use for randomly scattered points, but in certain cases it can be extremely helpful:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1689cd18-3d39-44ec-b35c-94a58baef036",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"tC6lDl\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"tC6lDl\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"direction = x\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[{\n",
       "\"aesthetic\":\"x\",\n",
       "\"limits\":[2.0,3.0]\n",
       "},{\n",
       "\"aesthetic\":\"y\",\n",
       "\"limits\":[1.0,1.3]\n",
       "}],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"y\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"nudge_y\":0.05,\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"y\":1.0,\n",
       "\"angle\":90.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"hjust\":0.0,\n",
       "\"direction\":\"x\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"19\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"direction = y\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[{\n",
       "\"aesthetic\":\"x\",\n",
       "\"limits\":[0.9,1.3]\n",
       "},{\n",
       "\"aesthetic\":\"y\",\n",
       "\"limits\":[19.0,35.0]\n",
       "}],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"nudge_x\":0.05,\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"hjust\":0.0,\n",
       "\"direction\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"20\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plotX = ggplot(df2.toMap()) { x = \"wt\"; label = \"model\" } +\n",
    "        geomPoint(y = 1, color = \"red\") + xlim(2 to 3) + ylim(1 to 1.3) +\n",
    "        geomTextRepel(y = 1, nudgeY = 0.05, direction = \"x\", angle = 90, hjust = 0.0, seed = seed)\n",
    "\n",
    "val plotY = ggplot(df2.toMap()) { y = \"mpg\"; label = \"model\" } +\n",
    "        geomPoint(x = 1, color = \"red\") + xlim(0.9 to 1.3) + ylim(19 to 35) +\n",
    "        geomTextRepel(x = 1, nudgeX = 0.05, direction = \"y\", hjust = 0.0, seed = seed)\n",
    "\n",
    "gggrid(\n",
    "    listOf(\n",
    "        plotX + ggtitle(\"direction = x\"),\n",
    "        plotY + ggtitle(\"direction = y\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47a85094-deb1-42e1-9f20-fbfc2b881b15",
   "metadata": {},
   "source": [
    "### `pointPadding` and `boxPadding` parameters\n",
    "These parameters control the amount of spacing around text labels.\n",
    "\n",
    "- `pointPadding` adds space between the label and all nearby points, but does not affect spacing between labels.\n",
    "\n",
    "- `boxPadding` adds space between labels, but does not affect spacing between the label and the data point."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f8dd256e-0371-4b2e-ab93-aeecb4a6560d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"Kwrkz9\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"Kwrkz9\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"pointPadding\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"point_padding\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"21\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"boxPadding\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"box_padding\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"22\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot2 + geomTextRepel(seed = seed, maxTime = -1.0, pointPadding = 10) + ggtitle(\"pointPadding\"),\n",
    "        plot2 + geomTextRepel(seed = seed, maxTime = -1.0, boxPadding = 10) + ggtitle(\"boxPadding\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9cfeffe-aed8-47e6-8a26-a73c958a65dc",
   "metadata": {},
   "source": [
    "### `maxOverlaps` parameter\n",
    "Specifies the maximum allowed number of overlaps with other labels. Labels that exceed this threshold will be omitted from the plot. The default value is `10`. You can disable overlap filtering entirely by setting this parameter to `-1`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "60ced1e9-99ea-49e0-8bb7-3b6952e9f64f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"bpOKaG\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"bpOKaG\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"maxOverlaps=5\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,32.4,21.5,15.5,15.2,26.0,15.8,19.7,15.0,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Hornet 4 Drive\",\"Hornet Sportabout\",\"Valiant\",\"Duster 360\",\"Merc 240D\",\"Merc 230\",\"Merc 280\",\"Merc 280C\",\"Fiat 128\",\"Toyota Corona\",\"Dodge Challenger\",\"AMC Javelin\",\"Porsche 914-2\",\"Ford Pantera L\",\"Ferrari Dino\",\"Maserati Bora\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,2.2,2.465,3.52,3.435,2.14,3.17,2.77,3.57,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"max_overlaps\":5.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"23\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"maxOverlaps=-1\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,32.4,21.5,15.5,15.2,26.0,15.8,19.7,15.0,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Hornet 4 Drive\",\"Hornet Sportabout\",\"Valiant\",\"Duster 360\",\"Merc 240D\",\"Merc 230\",\"Merc 280\",\"Merc 280C\",\"Fiat 128\",\"Toyota Corona\",\"Dodge Challenger\",\"AMC Javelin\",\"Porsche 914-2\",\"Ford Pantera L\",\"Ferrari Dino\",\"Maserati Bora\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,2.2,2.465,3.52,3.435,2.14,3.17,2.77,3.57,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"max_overlaps\":-1.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"24\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot1 + geomTextRepel(seed = seed, maxTime = -1.0, maxOverlaps = 5) + ggtitle(\"maxOverlaps=5\"),\n",
    "        plot1 + geomTextRepel(seed = seed, maxTime = -1.0, maxOverlaps = -1) + ggtitle(\"maxOverlaps=-1\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4ff9886-b49f-46b9-8541-e8bf80b41ad1",
   "metadata": {},
   "source": [
    "### `minSegmentLength` parameter\n",
    "Sets the minimum length for the line connecting a label to its associated point. Lines shorter than this length will not be drawn. To display all lines, use the default value of `0`. To hide all lines, set the value to something very large.\n",
    "`minSegmentLength` uses the same units as `pointSize`, so be careful when using `minSegmentLength` together with `sizeUnit` (see below)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "bcd4fd08-dab7-487e-a927-7d71df037a75",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"gOtcdn\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"gOtcdn\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"minSegmentLength=0\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,32.4,21.5,15.5,15.2,26.0,15.8,19.7,15.0,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Hornet 4 Drive\",\"Hornet Sportabout\",\"Valiant\",\"Duster 360\",\"Merc 240D\",\"Merc 230\",\"Merc 280\",\"Merc 280C\",\"Fiat 128\",\"Toyota Corona\",\"Dodge Challenger\",\"AMC Javelin\",\"Porsche 914-2\",\"Ford Pantera L\",\"Ferrari Dino\",\"Maserati Bora\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,2.2,2.465,3.52,3.435,2.14,3.17,2.77,3.57,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"min_segment_length\":0.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"25\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"minSegmentLength=9999\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,21.4,18.7,18.1,14.3,24.4,22.8,19.2,17.8,32.4,21.5,15.5,15.2,26.0,15.8,19.7,15.0,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Hornet 4 Drive\",\"Hornet Sportabout\",\"Valiant\",\"Duster 360\",\"Merc 240D\",\"Merc 230\",\"Merc 280\",\"Merc 280C\",\"Fiat 128\",\"Toyota Corona\",\"Dodge Challenger\",\"AMC Javelin\",\"Porsche 914-2\",\"Ford Pantera L\",\"Ferrari Dino\",\"Maserati Bora\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,3.215,3.44,3.46,3.57,3.19,3.15,3.44,3.44,2.2,2.465,3.52,3.435,2.14,3.17,2.77,3.57,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"min_segment_length\":9999.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"26\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "gggrid(\n",
    "    listOf(\n",
    "        plot1 + geomTextRepel(seed = seed, maxTime = -1.0, minSegmentLength = 0) + ggtitle(\"minSegmentLength=0\"),\n",
    "        plot1 + geomTextRepel(\n",
    "            seed = seed,\n",
    "            maxTime = -1.0,\n",
    "            minSegmentLength = 9999\n",
    "        ) + ggtitle(\"minSegmentLength=9999\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7870166b-b312-4f03-8c0d-471df42f2813",
   "metadata": {},
   "source": [
    "## Point settings\n",
    "`geomTextRepel()` does not draw points itself, but for it to work correctly, the values of parameters and aesthetics that control point size must match those used in the associated `geomPoint()` layer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "4fd33dd1-7a5b-4141-a83d-9cdfa32feafc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"HQuf07\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"HQuf07\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"shape\":[21.0,21.0,21.0,21.0,21.0,21.0,21.0,21.0],\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"vs\":[0.0,0.0,1.0,1.0,1.0,0.0,0.0,1.0],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78],\n",
       "\"gear\":[4.0,4.0,4.0,4.0,3.0,5.0,5.0,4.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[{\n",
       "\"aesthetic\":\"size\",\n",
       "\"range\":[0.5,1.0],\n",
       "\"guide\":\"none\"\n",
       "},{\n",
       "\"aesthetic\":\"stroke\",\n",
       "\"range\":[1.0,4.0],\n",
       "\"guide\":\"none\"\n",
       "},{\n",
       "\"aesthetic\":\"shape\",\n",
       "\"discrete\":true,\n",
       "\"scale_mapper_kind\":\"identity\",\n",
       "\"guide\":\"none\"\n",
       "}],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"shape\":\"shape\",\n",
       "\"size\":\"gear\",\n",
       "\"stroke\":\"vs\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "\"shape\":\"shape\",\n",
       "\"point_size\":\"gear\",\n",
       "\"point_stroke\":\"vs\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"27\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + geomPoint(sizeUnit = \"y\") { size = \"gear\"; stroke = \"vs\"; shape = \"shape\" }\n",
    "        + geomTextRepel(sizeUnit = \"y\") { pointSize = \"gear\"; pointStroke = \"vs\"; shape = \"shape\" }\n",
    "        + theme().legendPositionNone()\n",
    "        + scaleSize(range = 0.5 to 1, guide = \"none\")\n",
    "        + scaleStroke(range = 1 to 4, guide = \"none\")\n",
    "        + scaleShapeIdentity()\n",
    "        )\n",
    "    .show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d520d0fa-8329-45a6-a55f-f44a062463fd",
   "metadata": {},
   "source": [
    "### `pointSize` aesthetic\n",
    "Allows you to pass to `geomTextRepel()` the data used to determine point sizes in a `geomPoint()` layer. This helps accurately detect overlaps between labels and points when point sizes vary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6f4c0ff5-0fad-441a-a297-b91627a4ef1e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"FWXaWo\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"FWXaWo\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"without pointSize\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78],\n",
       "\"gear\":[4.0,4.0,4.0,4.0,3.0,5.0,5.0,4.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"size\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"28\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"with pointSize\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78],\n",
       "\"gear\":[4.0,4.0,4.0,4.0,3.0,5.0,5.0,4.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"size\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "\"point_size\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"29\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot31 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + geomPoint(color = \"red\") { size = \"gear\" }\n",
    "        + theme().legendPositionNone())\n",
    "\n",
    "gggrid(\n",
    "    listOf(\n",
    "        plot31 + geomTextRepel(seed = seed, maxTime = -1.0) + ggtitle(\"without pointSize\"),\n",
    "        plot31 + geomTextRepel(seed = seed, maxTime = -1.0) { pointSize = \"gear\" } + ggtitle(\"with pointSize\"),\n",
    "    )).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96b499b0-4fe8-4998-aff6-725ef02eff4f",
   "metadata": {},
   "source": [
    "You can also provide a constant value instead."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "7e5ce02c-ec1e-4e1b-8469-2f304b6c2e5d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"MINjdd\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"MINjdd\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"without pointSize\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"30\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"with pointSize\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"point_size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"31\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot32 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + geomPoint(size = 10, color = \"red\")\n",
    "        + theme().legendPositionNone())\n",
    "\n",
    "gggrid(\n",
    "    listOf(\n",
    "        plot32 + geomTextRepel(seed = seed, maxTime = -1.0) + ggtitle(\"without pointSize\"),\n",
    "        plot32 + geomTextRepel(seed = seed, maxTime = -1.0, pointSize = 10) + ggtitle(\"with pointSize\"),\n",
    "    )\n",
    ").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a3701287-59a8-4b08-ad36-35ad84a7b690",
   "metadata": {},
   "source": [
    "### `pointStroke` and `shape` aesthetics\n",
    "Allow you to pass to `geomTextRepel()` the data used to determine point stroke width and shape in a `geomPoint()` layer. This ensures accurate collision detection between labels and points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "588e87ad-e30c-44fc-a29d-d3f6f46a10f4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"okLJ7y\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"okLJ7y\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"without pointStroke\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78],\n",
       "\"gear\":[4.0,4.0,4.0,4.0,3.0,5.0,5.0,4.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"stroke\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"shape\":21.0,\n",
       "\"size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"point_size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"32\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"with pointStroke\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78],\n",
       "\"gear\":[4.0,4.0,4.0,4.0,3.0,5.0,5.0,4.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"stroke\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"shape\":21.0,\n",
       "\"size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "\"point_stroke\":\"gear\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"shape\":21.0,\n",
       "\"seed\":530.0,\n",
       "\"point_size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"33\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot33 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label=\"model\" }\n",
    "    + geomPoint(shape=21, size=10, color=\"red\") { stroke=\"gear\" }\n",
    "    + theme().legendPositionNone())\n",
    "\n",
    "gggrid(listOf(\n",
    "    plot33 + geomTextRepel(seed=seed, maxTime=-1.0, pointSize=10) + ggtitle(\"without pointStroke\"),\n",
    "    plot33 + geomTextRepel(shape=21, pointSize=10, seed=seed, maxTime=-1.0) { pointStroke=\"gear\" } + ggtitle(\"with pointStroke\"),\n",
    ")).show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6416d311-a608-40c8-a442-191882e97227",
   "metadata": {},
   "source": [
    "### `sizeUnit` parameter\n",
    "The `sizeUnit` parameter can be used in `geomPoint()` to define the unit of measurement for the `size` aesthetic. In this case, it is recommended to also use `sizeUnit` in `geomTextRepel()` to ensure that point sizes are calculated correctly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b18e356c-1418-4067-95e5-ae7245331556",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"5BfDWW\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"5BfDWW\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"without sizeUnit\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"point_size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"34\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"with sizeUnit\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"point_size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"35\"\n",
       "}],\n",
       "\"kind\":\"subplots\",\n",
       "\"ggtoolbar\":{\n",
       "}\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot4 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + geomPoint(size = 1, sizeUnit = \"y\", color = \"red\")\n",
    "        + theme().legendPositionNone())\n",
    "\n",
    "(gggrid(\n",
    "    listOf(\n",
    "        plot4 + geomTextRepel(seed = seed, maxTime = -1.0, pointSize = 1) + ggtitle(\"without sizeUnit\"),\n",
    "        plot4 + geomTextRepel(\n",
    "            seed = seed,\n",
    "            maxTime = -1.0,\n",
    "            pointSize = 1,\n",
    "            sizeUnit = \"y\"\n",
    "        ) + ggtitle(\"with sizeUnit\"),\n",
    "    )\n",
    ") + ggtb()).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5de7618-3475-465a-9af3-063f733dd68f",
   "metadata": {},
   "source": [
    "##### `sizeUnit` applies to all size-related parameters: `pointSize`, `minSegmentLength`, `pointPadding`, and `boxPadding`.\n",
    "As an example, consider how it affects `minSegmentLength`.\n",
    "As mentioned earlier, `minSegmentLength` uses the same units as `pointSize`. Therefore, in the following example, with the same `minSegmentLength` value, some lines are not drawn in the second case because their length is less than one unit along the y-axis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "69063269-f4bb-43d0-ba7e-8d3e84a4cd90",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"TXVcUd\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"TXVcUd\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":2,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"without sizeUnit\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"min_segment_length\":1.0,\n",
       "\"point_size\":10.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"36\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"with sizeUnit\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"min_segment_length\":1.0,\n",
       "\"point_size\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"size_unit\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"37\"\n",
       "}],\n",
       "\"kind\":\"subplots\",\n",
       "\"ggtoolbar\":{\n",
       "}\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot5 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + theme().legendPositionNone())\n",
    "\n",
    "(gggrid(\n",
    "    listOf(\n",
    "        (plot5 + geomPoint(size = 10, color = \"red\")\n",
    "                + geomTextRepel(seed = seed, maxTime = -1.0, pointSize = 10, minSegmentLength = 1)\n",
    "                + ggtitle(\"without sizeUnit\")),\n",
    "        (plot5 + geomPoint(size = 1, sizeUnit = \"y\", color = \"red\")\n",
    "                + geomTextRepel(seed = seed, maxTime = -1.0, pointSize = 1, minSegmentLength = 1, sizeUnit = \"y\")\n",
    "                + ggtitle(\"with sizeUnit\")),\n",
    "    )\n",
    ") + ggtb()).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ed6370a-942e-4d3a-8c33-deada9565d7d",
   "metadata": {},
   "source": [
    "### `segmentColor` aesthetic\n",
    "Allows you to specify the color of the line connecting the label to the point. By default, the line color matches the text color and follows the `color` aesthetic. In the example below, the `color` aesthetic is defined globally for all layers, so the colors of the points, text, and lines are the same."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "cb322efa-8f0a-4609-b58b-a1d4b02deee4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"jCSt5N\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"jCSt5N\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"color\":\"wt\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"38\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\"; color = \"wt\" }\n",
    "        + geomPoint()\n",
    "        + geomTextRepel(seed = seed, maxTime = -1.0)\n",
    "        )\n",
    "    .show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "868e31d0-36cc-4ef5-9304-e4d622ab5a7f",
   "metadata": {},
   "source": [
    "By using the `color` and `segmentColor` aesthetics together, you can assign different colors to the points, labels, and connecting lines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "23c59549-79fc-4f5d-9ff7-2c6269368144",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"lP42HS\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"lP42HS\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"layout\":{\n",
       "\"name\":\"grid\",\n",
       "\"ncol\":3,\n",
       "\"nrow\":1,\n",
       "\"fit\":true,\n",
       "\"align\":false\n",
       "},\n",
       "\"figures\":[{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Same color for points and lines\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "\"color\":\"wt\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "\"segment_color\":\"wt\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"39\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Same color for text and line\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "\"color\":\"wt\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"40\"\n",
       "},{\n",
       "\"ggtitle\":{\n",
       "\"text\":\"Different colors\"\n",
       "},\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"green\",\n",
       "\"seed\":530.0,\n",
       "\"segment_color\":\"blue\",\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"theme\":{\n",
       "\"legend_position\":\"none\"\n",
       "},\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"41\"\n",
       "}],\n",
       "\"kind\":\"subplots\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "val plot6 = (ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + theme().legendPositionNone())\n",
    "\n",
    "gggrid(\n",
    "    listOf(\n",
    "        plot6 + geomPoint() { color = \"wt\" }\n",
    "                + geomTextRepel(seed = seed, maxTime = -1.0) { segmentColor = \"wt\" }\n",
    "                + ggtitle(\"Same color for points and lines\"),\n",
    "        plot6 + geomPoint(color = \"red\")\n",
    "                + geomTextRepel(seed = seed, maxTime = -1.0) { color = \"wt\" }\n",
    "                + ggtitle(\"Same color for text and line\"),\n",
    "        plot6 + geomPoint(color = \"red\")\n",
    "                + geomTextRepel(color = \"green\", segmentColor = \"blue\", seed = seed, maxTime = -1.0)\n",
    "                + ggtitle(\"Different colors\"),\n",
    "    )).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de08c1f3-18c1-42af-b9cf-fdfe50e06669",
   "metadata": {},
   "source": [
    "### `segmentAlpha` aesthetic\n",
    "\n",
    "Specifies the transparency level of the connecting lines between labels and points. By default, the segment transparency inherits from the text and is governed by the `alpha` aesthetic."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "4ac608a2-3a48-4e9d-a8bf-93cadb0fcaa7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"eWmsIR\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"eWmsIR\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"seed\":530.0,\n",
       "\"point_padding\":20.0,\n",
       "\"segment_alpha\":0.1,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"42\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(ggplot(df2.toMap()) { x = \"wt\"; y = \"mpg\"; label = \"model\" }\n",
    "        + geomPoint(color = \"red\")\n",
    "        + geomTextRepel(pointPadding = 20, color = \"red\", segmentAlpha = 0.1, seed = seed, maxTime = -1.0)\n",
    "        ).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a15e840f-4bde-4841-96b4-aeede9b10498",
   "metadata": {},
   "source": [
    "### `segmentSize` aesthetic\n",
    "Specifies the width of the line connecting the label to the point."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "9e20ad8d-d7a6-4001-923c-5c93b390259a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"0wrL8w\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"0wrL8w\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"x\":\"wt\",\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"wt\":[2.62,2.875,2.32,2.2,2.465,2.14,2.77,2.78]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"segment_size\":2.0,\n",
       "\"seed\":530.0,\n",
       "\"position\":\"identity\",\n",
       "\"max_time\":-1.0,\n",
       "\"geom\":\"text_repel\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"43\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(plot2 + geomTextRepel(segmentSize=2, seed=seed, maxTime=-1.0)).show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9d213d9-beba-41ba-8625-a8d770854d65",
   "metadata": {},
   "source": [
    "### `linetype` aesthetic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "77421562-83f3-4f80-b572-6a45b9ab2cec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"NDy9QY\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"NDy9QY\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"],\n",
       "\"disp\":[160.0,160.0,108.0,78.7,120.1,120.3,145.0,121.0]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[{\n",
       "\"aesthetic\":\"x\",\n",
       "\"limits\":[0.9,1.3]\n",
       "},{\n",
       "\"aesthetic\":\"y\",\n",
       "\"limits\":[19.0,35.0]\n",
       "}],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"nudge_x\":0.2,\n",
       "\"mapping\":{\n",
       "\"linetype\":\"disp\"\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"hjust\":0.0,\n",
       "\"direction\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"44\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(ggplot(df2.toMap()) { y=\"mpg\"; label=\"model\" } + geomPoint(x=1, color=\"red\") + xlim(0.9 to 1.3) + ylim(19 to 35)\n",
    "    + geomTextRepel(x=1, nudgeX=0.2, direction=\"y\", hjust=0.0, seed=seed) { linetype=\"disp\" })\n",
    "    .show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a951ee9-2752-4aa2-b206-7bc9d9980e03",
   "metadata": {},
   "source": [
    "### `arrow` parameter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "0af8fccd-a08a-4125-b258-8a45b442b48f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "   <div id=\"l8CL57\"></div>\n",
       "   <script type=\"text/javascript\" data-lets-plot-script=\"plot\">\n",
       "   \n",
       "   (function() {\n",
       "   // ----------\n",
       "   \n",
       "   const forceImmediateRender = false;\n",
       "   const responsive = false;\n",
       "   \n",
       "   let sizing = {\n",
       "       width_mode: \"MIN\",\n",
       "       height_mode: \"SCALED\",\n",
       "       width: null, \n",
       "       height: null \n",
       "   };\n",
       "   \n",
       "   const preferredWidth = document.body.dataset.letsPlotPreferredWidth;\n",
       "   if (preferredWidth !== undefined) {\n",
       "       sizing = {\n",
       "           width_mode: 'FIXED',\n",
       "           height_mode: 'SCALED',\n",
       "           width: parseFloat(preferredWidth)\n",
       "       };\n",
       "   }\n",
       "   \n",
       "   const containerDiv = document.getElementById(\"l8CL57\");\n",
       "   let fig = null;\n",
       "   \n",
       "   function renderPlot() {\n",
       "       if (fig === null) {\n",
       "           const plotSpec = {\n",
       "\"mapping\":{\n",
       "\"y\":\"mpg\",\n",
       "\"label\":\"model\"\n",
       "},\n",
       "\"data\":{\n",
       "\"mpg\":[21.0,21.0,22.8,32.4,21.5,26.0,19.7,21.4],\n",
       "\"model\":[\"Mazda RX4\",\"Mazda RX4 Wag\",\"Datsun 710\",\"Fiat 128\",\"Toyota Corona\",\"Porsche 914-2\",\"Ferrari Dino\",\"Volvo 142E\"]\n",
       "},\n",
       "\"kind\":\"plot\",\n",
       "\"scales\":[{\n",
       "\"aesthetic\":\"x\",\n",
       "\"limits\":[0.9,1.3]\n",
       "},{\n",
       "\"aesthetic\":\"y\",\n",
       "\"limits\":[19.0,35.0]\n",
       "}],\n",
       "\"layers\":[{\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"color\":\"red\",\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"point\",\n",
       "\"data\":{\n",
       "}\n",
       "},{\n",
       "\"nudge_x\":0.2,\n",
       "\"mapping\":{\n",
       "},\n",
       "\"stat\":\"identity\",\n",
       "\"seed\":530.0,\n",
       "\"arrow\":{\n",
       "\"name\":\"arrow\",\n",
       "\"angle\":10.0,\n",
       "\"ends\":\"both\",\n",
       "\"type\":\"closed\"\n",
       "},\n",
       "\"x\":1.0,\n",
       "\"position\":\"identity\",\n",
       "\"geom\":\"text_repel\",\n",
       "\"hjust\":0.0,\n",
       "\"direction\":\"y\",\n",
       "\"data\":{\n",
       "}\n",
       "}],\n",
       "\"data_meta\":{\n",
       "\"series_annotations\":[{\n",
       "\"type\":\"str\",\n",
       "\"column\":\"model\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"mpg\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"cyl\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"disp\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"hp\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"drat\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"wt\"\n",
       "},{\n",
       "\"type\":\"float\",\n",
       "\"column\":\"qsec\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"vs\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"am\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"gear\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"carb\"\n",
       "},{\n",
       "\"type\":\"int\",\n",
       "\"column\":\"shape\"\n",
       "}]\n",
       "},\n",
       "\"spec_id\":\"45\"\n",
       "};\n",
       "           window.letsPlotCall(function() { fig = LetsPlot.buildPlotFromProcessedSpecs(plotSpec, containerDiv, sizing); });\n",
       "       } else {\n",
       "           fig.updateView({});\n",
       "       }\n",
       "   }\n",
       "   \n",
       "   const renderImmediately = \n",
       "       forceImmediateRender || (\n",
       "           sizing.width_mode === 'FIXED' && \n",
       "           (sizing.height_mode === 'FIXED' || sizing.height_mode === 'SCALED')\n",
       "       );\n",
       "   \n",
       "   if (renderImmediately) {\n",
       "       renderPlot();\n",
       "   }\n",
       "   \n",
       "   if (!renderImmediately || responsive) {\n",
       "       // Set up observer for initial sizing or continuous monitoring\n",
       "       var observer = new ResizeObserver(function(entries) {\n",
       "           for (let entry of entries) {\n",
       "               if (entry.contentBoxSize && \n",
       "                   entry.contentBoxSize[0].inlineSize > 0) {\n",
       "                   if (!responsive && observer) {\n",
       "                       observer.disconnect();\n",
       "                       observer = null;\n",
       "                   }\n",
       "                   renderPlot();\n",
       "                   if (!responsive) {\n",
       "                       break;\n",
       "                   }\n",
       "               }\n",
       "           }\n",
       "       });\n",
       "       \n",
       "       observer.observe(containerDiv);\n",
       "   }\n",
       "   \n",
       "   // ----------\n",
       "   })();\n",
       "   \n",
       "   </script>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(ggplot(df2.toMap()) { y=\"mpg\"; label=\"model\" }\n",
    "        + geomPoint(x=1, color=\"red\")\n",
    "        + geomTextRepel(\n",
    "            x = 1,\n",
    "            nudgeX = 0.2,\n",
    "            direction = \"y\",\n",
    "            hjust = 0.0,\n",
    "            arrow = arrow(type = \"closed\", angle = 10, ends = \"both\"),\n",
    "            seed = seed\n",
    "        )\n",
    "        + xlim(0.9 to 1.3)\n",
    "        + ylim(19 to 35)\n",
    "    ).show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Kotlin",
   "language": "kotlin",
   "name": "kotlin"
  },
  "language_info": {
   "codemirror_mode": "text/x-kotlin",
   "file_extension": ".kt",
   "mimetype": "text/x-kotlin",
   "name": "kotlin",
   "nbconvert_exporter": "",
   "pygments_lexer": "kotlin",
   "version": "1.9.23"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
